package com.class5.springboot.frame.repo;

import com.class5.springboot.frame.repo.dto.ParamMap;

import java.util.ArrayList;

import java.util.Arrays;
import java.util.List;


public class Condition {
    private List<String> tokens = new ArrayList<>();
    private List<Object> params = new ArrayList<Object>();
    private Sql sql = null;
    private String prefix = null;
    public Condition(String prefix, Sql sql) {
        if(prefix == null)
            throw new RuntimeException("前缀不能为空");
        this.sql = sql;
        this.prefix = prefix;
    }
    /**
     * 通过map自动构建查询条件
     * 根据参数名来定规则
     * xxx_begin名称结尾的将用 >=
     * xxx_end名称结算的将用<=
     * 其它将使用=
     * 如果参数值为空或空串将跳过
     * 其中xxx为列名
     * @param map
     */
    public Condition filter(ParamMap map, String columnPrefix, String[] includes, String[] excludes){
        if(excludes == null){
            excludes = new String[]{"limit","page"};
        }
        if(columnPrefix != null && !isNullObject(columnPrefix)){
            if(columnPrefix.indexOf(".") < 0){
                columnPrefix = columnPrefix + ".";
            }
        }
        for(String key : map.keySet()){
            Object val = map.get(key);
            if(isNullObject(val))
                continue;
            //考虑排除
            boolean ext = false;
            if(excludes != null){
                for(String s : excludes){
                    if(s.equals(key)){
                        ext = true;
                        break;
                    }
                }
            }
            if(ext)
                continue;

            if(key.endsWith("_begin")){
                String prop = key.substring(0, key.lastIndexOf("_"));
                if(!isNullObject(columnPrefix))
                    prop = columnPrefix + prop;
                if(isInclude(prop, includes))
                    gte(prop, val);
            }else if(key.endsWith("_end")){
                String prop = key.substring(0, key.lastIndexOf("_"));
                if(!isNullObject(columnPrefix))
                    prop = columnPrefix + prop;
                if(isInclude(prop, includes))
                    lte(prop, val);
            }else{
                if(!isNullObject(columnPrefix))
                    key = columnPrefix + key;
                if(isInclude(key, includes))
                    eq(key, val);
            }
        }
        return this;
    }

    private boolean isInclude(String name, String[] includes){
        if(includes == null)
            return true;
        for(String s : includes){
            if(name.equals(s)){
                return true;
            }
        }
        return false;
    }
    /**
     * 添加=条件
     * @param column
     * @param param
     * @return
     */
    public Condition eq(String column , Object param){
        return addItem(column, "=", false, param);
    }

    /**
     * 添加!=条件
     * @param column
     * @param param
     * @return
     */
    public Condition notEq(String column , Object param){
        return addItem(column, "!=", false, param);
    }


    /**
     * 添加>条件
     * @param column
     * @param param
     * @return
     */
    public Condition gt(String column , Object param){
        return addItem(column, ">", false, param);
    }
    /**
     * 添加>=条件
     * @param column
     * @param param
     * @return
     */
    public Condition gte(String column , Object param){
        return addItem(column, ">=", false, param);
    }
    /**
     * 添加<条件
     * @param column
     * @param param
     * @return
     */
    public Condition lt(String column , Object param){
        return addItem(column, "<", false, param);
    }
    /**
     * 添加<=条件
     * @param column
     * @param param
     * @return
     */
    public Condition lte(String column , Object param){
        return addItem(column, "<=", false, param);
    }
    /**
     * 添加like %xxx%条件
     * @param column
     * @param param
     * @return
     */
    public Condition like(String column , Object param){
        if(!isNullObject(param)){
            return addItem(column, "like", false, "%" +param+"%");
        }
        return this;
    }
    /**
     * 添加like xxx%条件
     * @param column
     * @param param
     * @return
     */
    public Condition rlike(String column , Object param){
        if(!isNullObject(param)){
            return addItem(column, "like", false, param + "%");
        }
        return this;
    }
    /**
     * 添加like %xxx条件
     * @param column
     * @param param
     * @return
     */
    public Condition llike(String column , Object param){
        if(!isNullObject(param)){
            return addItem(column, "like", false, "%" +param);
        }
        return this;
    }
    /**
     * 添加in条件
     * @param name
     * @param params
     * @return
     */
    public Condition in(String column, Object... params) {
        return addItem2(column, "in", false, true, params);
    }

    /**
     * 添加一个子条件
     * @param column
     * @param opt
     * @param mustflag
     * @param params
     * @return
     */
    private Condition addItem(String column, String opt, boolean mustflag, Object... params){
        return addItem2(column, opt, mustflag, false, params);
    }
    private Condition addItem2(String column, String opt, boolean mustflag, boolean mustbracket, Object... params){
        String qstr = "";
        if(!mustflag && params != null){
            for(Object obj : params){
                if(!isNullObject(obj)){
                    mustflag = true;
                }
                qstr = qstr + "?,";
            }
            if(!qstr.isEmpty())
                qstr = qstr.substring(0, qstr.length()-1);
            if((params != null && params.length > 1) || mustbracket){
                qstr = "(" + qstr + ")";
            }
        }
        if(mustflag){
            if(opt != null && !opt.isEmpty())
                this.tokens.add(column + " " + opt + " " + qstr);
            else
                this.tokens.add(column);
            this.params.addAll(Arrays.asList(params));
        }
        return this;
    }
    private boolean isNullObject(Object obj){
        if(obj instanceof String){
            return ((String)obj).isEmpty();
        }
        return obj == null;
    }
    /**
     * 获取语句
     * @return
     */
    public String getSql(){
        StringBuffer sb = new StringBuffer();
        for(String str : tokens){
            sb.append(str + " AND ");
        }
        if(sb.indexOf("AND") > 0){
            return prefix + " " + sb.substring(0, sb.length()-5);
        }
        return "";
    }
    /**
     * 获取参数
     * @return
     */
    public Object[] getParams(){
        return this.params.toArray();
    }
    /**
     * 添加子条件
     * @param sql
     * @param params
     * @return
     */
    public Condition add(String sql, Object... params){
        return addItem(sql, null, true, params);
    }
    /**
     * exists
     * @param sql
     * @param params
     * @return
     */
    public Condition exists(String sql, Object... params){
        return add("EXISTS(" + sql + ")", params);
    }
    /**
     * is null
     * @param column
     * @return
     */
    public Condition isNull(String column){
        return addItem(column, "IS NULL", true);
    }
    /**
     * 如果参数为空转成is null
     * 否则使用=
     * @param column
     * @param obj
     * @return
     */
    public Condition eqMust(String column, Object obj){
        if(isNullObject(obj)){
            return isNull(column);
        }else{
            return addItem(column, "=", false, obj);
        }
    }
    /**
     * 使用is not null
     * @param column
     * @param obj
     * @return
     */
    public Condition isNotNull(String column){
        return addItem(column, "IS NOT NULL", true);
    }
    /**
     * 返回SQL对象
     * @return
     */
    public Sql parent(){
        //附加到sql
        sql.addSql(getSql(), getParams());
        return sql;
    }
    @Override
    public String toString() {
        return "Sql:" + getSql() + ",params:" + params;
    }
}